package com.astrofizzbizz.stoneedgegui.utilities;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SkyTargetChart extends JPanel
{
	private static final long serialVersionUID = 1033209667870933040L;
	static double jan1Offset = 40587.0;
	private int chartSize = 500;
	private double latitude = 45;
	private double longitude = -89;
	private double time = 55197.22;
	private double presentAz = 132.0;
	private double presentAlt = 45.0;
	private double targetAz = 100.0;
	private double targetAlt = 10.0;
	private BufferedImage bufferedImage = null;
	private JLabel imageLabel =  new JLabel();
	public SkyTargetChart(int chartSize , double latitude, double longitude, 
			double presentAz, double presentAlt, double targetAz, double targetAlt, Date date)
	{
		super();
		this.chartSize = chartSize;
		this.latitude = latitude;
		this.longitude = longitude;
		this.presentAz = presentAz;
		this.presentAlt = presentAlt;
		this.targetAz = targetAz;
		this.targetAlt = targetAlt;
		setTime(date);
		add(imageLabel);
		updateChart();
	}
	public SkyTargetChart(int chartSize , double latitude, double longitude, 
			String raPres, String decPres, String raTarg, String decTarg, Date date)
	{
		super();
		this.chartSize = chartSize;
		this.latitude = latitude;
		this.longitude = longitude;
		setTime(date);
		
		setPresentRaDec(raPres, decPres);
		setTargetRaDec(raTarg, decTarg);
		add(imageLabel);
		updateChart();
	}
	public void updateChart()
	{
		makeSkyTargetChart();
		imageLabel.setIcon(new ImageIcon(bufferedImage));
	}
	
	private void makeSkyTargetChart()
	{
		Image image = null;
		String mapUrl = "";
		mapUrl = mapUrl + "http://www.heavens-above.com/wholeskychart.ashx?lat=";
		mapUrl = mapUrl + latitude;
		mapUrl = mapUrl + "&lng=";
		mapUrl = mapUrl + longitude;
		mapUrl = mapUrl + "&size=";
		mapUrl = mapUrl + chartSize;
		mapUrl = mapUrl + "&SL=1&SN=1&BW=1&time=";
		mapUrl = mapUrl + time;
		try {
		        // Read from a URL
			URL url = new URL(mapUrl);
//System.out.println(mapUrl);
			image = ImageIO.read(url);
		} catch (IOException e) 
		{
		}
		bufferedImage = new BufferedImage(chartSize,chartSize,BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics2D = bufferedImage.createGraphics();
		graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
					RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		graphics2D.drawImage(image, 0, 0, chartSize, chartSize, null);

		double thetaPresent = presentAz + 180;
		for (int ii = 0; ii < chartSize/2; ++ii)
		{
			int ired = 0;
			int igreen = 0;
			int iblue = 255;
			Color	clr  = new Color(ired, igreen, iblue);
			double dx = ((double) ii) * Math.sin(thetaPresent * Math.PI / 180.0) + chartSize/2;
			double dy = ((double) ii) * Math.cos(thetaPresent * Math.PI / 180.0) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			double ddx = dx + Math.cos(thetaPresent * Math.PI / 180.0);
			double ddy = dy - Math.sin(thetaPresent * Math.PI / 180.0);
			bufferedImage.setRGB((int) ddx, (int) ddy, clr.getRGB());
			ddx = dx - Math.cos(thetaPresent * Math.PI / 180.0);
			ddy = dy + Math.sin(thetaPresent * Math.PI / 180.0);
			bufferedImage.setRGB((int) ddx, (int) ddy, clr.getRGB());
		}
		double thetaTarget = targetAz + 180;
		for (int ii = 0; ii < chartSize/2; ++ii)
		{
			int ired = 0;
			int igreen = 255;
			int iblue = 0;
			Color	clr  = new Color(ired, igreen, iblue);
			double dx = ((double) ii) * Math.sin(thetaTarget * Math.PI / 180.0) + chartSize/2;
			double dy = ((double) ii) * Math.cos(thetaTarget * Math.PI / 180.0) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			double ddx = dx + Math.cos(thetaTarget * Math.PI / 180.0);
			double ddy = dy - Math.sin(thetaTarget * Math.PI / 180.0);
			bufferedImage.setRGB((int) ddx, (int) ddy, clr.getRGB());
			ddx = dx - Math.cos(thetaTarget * Math.PI / 180.0);
			ddy = dy + Math.sin(thetaTarget * Math.PI / 180.0);
			bufferedImage.setRGB((int) ddx, (int) ddy, clr.getRGB());
		}
		int circleNpts = 360 * 2;
		double radius = (1 - presentAlt / 90.0) * chartSize/2;
		if (radius >= 0.99 * chartSize/2) radius = 0.99 * chartSize/2;
		for (int ii = 0; ii < circleNpts; ++ii)
		{
			int ired = 0;
			int igreen = 0;
			int iblue = 255;
			Color	clr  = new Color(ired, igreen, iblue);
			double dx = radius * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			double dy = radius * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			dx = (radius + 1) * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			dy = (radius + 1) * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			dx = (radius - 1) * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			dy = (radius - 1) * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
		}
		radius = (1 - targetAlt / 90.0) * chartSize/2;
		if (radius >= 0.99 * chartSize/2) radius = 0.99 * chartSize/2;
		for (int ii = 0; ii < circleNpts; ++ii)
		{
			int ired = 0;
			int igreen = 255;
			int iblue = 0;
			Color	clr  = new Color(ired, igreen, iblue);
			double dx = radius * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			double dy = radius * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			dx = (radius + 1) * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			dy = (radius + 1) * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
			dx = (radius - 1) * Math.sin(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1)) ) + chartSize/2;
			dy = (radius - 1) * Math.cos(((double) ii) * 2.0 * Math.PI / ((double)(circleNpts - 1))) + chartSize/2;
			bufferedImage.setRGB((int) dx, (int) dy, clr.getRGB());
		}
	}
	public void makeJFrame()
	{
		makeSkyTargetChart();
		// Use a label to display the image
		JFrame frame = new JFrame();
		JLabel label = new JLabel(new ImageIcon(bufferedImage));
		frame.getContentPane().add(label, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);
	}
	public void makePngPlot(String fileName)
	{
		try {
			ImageIO.write(bufferedImage, "png", new File(fileName));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public int getChartSize() {
		return chartSize;
	}

	public void setChartSize(int chartSize) {
		this.chartSize = chartSize;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public Date getTime() {
		double tempTime = time - jan1Offset;
		tempTime = tempTime * 3600.0 * 24.0 * 1000.0;
		return new Date((long) tempTime);
	}
	public void setTime(Date date) 
	{
		time = ((double) date.getTime())/ 1000.0 / 24.0 / 3600;
		time = time + jan1Offset;
	}
	public void setPresentAltAz(double alt, double az) {
		presentAz = az;
		presentAlt = alt;
	}
	public void setTargetAltAz(double alt, double az) {
		targetAz = az;
		targetAlt = alt;
	}
	public void setPresentRaDec(double raDeg, double decDeg) 
	{
		double[] altAz  = StarCoordUtilities.getAltAzDeg(raDeg, decDeg, longitude, latitude, getTime());
		presentAz = altAz[1];
		presentAlt = altAz[0];
	}
	public void setTargetRaDec(double raDeg, double decDeg) 
	{
		double[] altAz  = StarCoordUtilities.getAltAzDeg(raDeg, decDeg, longitude, latitude, getTime());
		targetAz = altAz[1];
		targetAlt = altAz[0];
	}
	public void setPresentRaDec(String raString, String decString) 
	{
		double raDeg = StarCoordUtilities.raDeg(raString);
		double decDeg = StarCoordUtilities.decDeg(decString);
		double[] altAz  = StarCoordUtilities.getAltAzDeg(raDeg, decDeg, longitude, latitude, getTime());
		presentAz = altAz[1];
		presentAlt = altAz[0];
	}
	public void setTargetRaDec(String raString, String decString) 
	{
		double raDeg = StarCoordUtilities.raDeg(raString);
		double decDeg = StarCoordUtilities.decDeg(decString);
		double[] altAz  = StarCoordUtilities.getAltAzDeg(raDeg, decDeg, longitude, latitude, getTime());
		targetAz = altAz[1];
		targetAlt = altAz[0];
	}

	public static void main(String[] args) 
	{
		int chartSize = 500;
		double latitude = 38.29341507;
		double longitude = -122.47058868;

		String raPres = "16:07:15.59";
		String decPres = "-17:23:44.3";
		String raTarg = "17:46:17.88";
		String decTarg = "-21:54:13.3";
		
		SkyTargetChart sktc = new SkyTargetChart(chartSize, latitude, longitude, raPres, decPres, raTarg, decTarg, new Date());
		
		JFrame frame = new JFrame();
		frame.getContentPane().add(sktc, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);
		
		while (true)
		{
			sktc.setTime(new Date());
			sktc.updateChart();	
			try {Thread.sleep(1000);} catch (InterruptedException e) {}
		}

		
	}

}
